﻿using System;
using Microsoft.Data.SqlClient;
using Microsoft.EntityFrameworkCore;

namespace Smartstore
{
    public static class DataExceptionExtensions
    {
        /// <summary>
        /// Checks whether the inner exception indicates uniqueness violation
        /// (is 2627 = Unique constraint error, OR is 547 = Constraint check violation, OR is 2601 = Duplicated key row error)
        /// </summary>
        /// <param name="exception">The exception wrapper</param>
        /// <returns></returns>
        public static bool IsUniquenessViolationException(this DbUpdateException exception)
        {
            // TODO: (core) What type is MySql's InnerException?
            
            var sqlException = exception?.InnerException as SqlException;

            if (sqlException == null)
                sqlException = exception?.InnerException?.InnerException as SqlException;

            if (sqlException == null)
                return false;
            
            switch (sqlException.Number)
            {
                case 2627:  // Unique constraint error
                case 547:   // Constraint check violation
                case 2601:  // Duplicated key row error
                    return true;
                default:
                    return false;
            }
        }

        ///// <summary>
        ///// Checks whether the inner exception indicates a deadlock error
        ///// </summary>
        ///// <param name="exception">The exception wrapper</param>
        ///// <returns></returns>
        //public static bool IsDeadlockException(this EntityCommandExecutionException exception)
        //{
        //    var sqlException = exception?.InnerException as SqlException;

        //    if (sqlException == null)
        //        sqlException = exception?.InnerException?.InnerException as SqlException;

        //    if (sqlException == null)
        //        return false;

        //    return sqlException.IsDeadlockException();
        //}

        /// <summary>
        /// Checks whether the exception indicates a deadlock error (1205)
        /// </summary>
        /// <param name="exception">The exception wrapper</param>
        /// <returns></returns>
        public static bool IsDeadlockException(this SqlException exception)
        {
            if (exception == null)
                return false;

            return exception.Number == 1205;
        }

        /// <summary>
        /// Checks whether the exception indicates attaching an already attached entity (HResult -2146233079)
        /// "Attaching an entity of type 'x' failed because another entity of the same type already has the same primary key value."
        /// </summary>
        /// <param name="exception">Invalid operation exception</param>
        /// <returns></returns>
        public static bool IsAlreadyAttachedEntityException(this InvalidOperationException exception)
        {
            return exception != null && exception.HResult == -2146233079;
        }
    }
}